package online.flowerinsnow.demo1;

import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;

import java.util.HashMap;

public class Main extends JavaPlugin implements Listener {
    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(this, this);
    }

    @Override
    public void onDisable() {
        getServer().getScheduler().cancelTasks(this); // 在插件卸载时，把所有该插件的计划任务全都取消掉
        playerTasks.clear(); // 清空现有的计划任务实例
    }

    /**
     * 玩家作为Key 计划任务对象作为Value
     * 用于记录符合条件的玩家名单
     * 这里直接传Player 要是想传UUID也是可以的
     * 因为都在同一个线程 所以不需要加线程锁
     */
    private final HashMap<Player, BukkitTask> playerTasks = new HashMap<>();

    /*
     * 目标：当一个玩家的游戏模式是生存模式时，始终允许他飞行
     * 思路：玩家模式切换后，判断玩家是不是生存，如果是，就给他一个单独的计划任务
     * 一旦玩家不是生存了，这个计划任务就会被取消掉
     */

    @EventHandler
    public void onGameModeChange(PlayerGameModeChangeEvent e) {
        if (e.getNewGameMode() == GameMode.SURVIVAL) { // 玩家即将切换到生存模式
            this.runTaskToPlayer(e.getPlayer()); // 给玩家创建计划任务
        } else { // 否则 取消计划任务
            this.cancelTaskToPlayer(e.getPlayer());
        }
    }

    /**
     * 该方法用于给玩家创建计划任务
     *
     * @param player 目标玩家
     */
    private void runTaskToPlayer(Player player) {
        if (playerTasks.get(player) != null) {
            return; // 不要让同样的计划任务同时存在两份 先判断一下 如果已经有该任务了 就不再启动第二个计划任务了
        }

        // 启动计划任务 并且把它存起来
        BukkitTask task = getServer().getScheduler().runTaskTimer(this, () ->
            player.setAllowFlight(true) // 每次执行都给这个玩家上一次允许飞行
        , 0L, 1L); // 0Tick后执行 之后每1Tick执行一次 也就是接下来每一Tick都执行
        playerTasks.put(player, task); // 存储起来，方便下次调用
    }

    /**
     * 该方法用于给玩家取消计划任务
     *
     * @param player 目标玩家
     */
    private void cancelTaskToPlayer(Player player) {
        BukkitTask task = playerTasks.remove(player); // 尝试获取玩家当前拥有的计划任务 并将其删除
        if (task != null) { // 如果计划任务是存在的
            task.cancel(); // 将该计划任务取消，后面这个任务就不会继续执行了
        }
    }

    /*
    后面还有一些要注意的，玩家进入和退出时都要判断一次
     */

    @EventHandler
    public void onJoin(PlayerJoinEvent e) {
        if (e.getPlayer().getGameMode() == GameMode.SURVIVAL) { // 如果进来的玩家是生存模式
            this.runTaskToPlayer(e.getPlayer()); // 开启计划任务
        }
    }

    @EventHandler
    public void onQuit(PlayerQuitEvent e) {
        // 玩家退了 就不要让僵尸任务接着跑了
        this.cancelTaskToPlayer(e.getPlayer());
    }
}
